home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / ncpfs / ipxripd-.000 / ipxripd- / ipxripd / ipxd.c < prev    next >
C/C++ Source or Header  |  1996-02-08  |  12KB  |  728 lines

  1. /*
  2.     IPX routing daemon
  3.  
  4.     Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. */
  21.  
  22. #include <signal.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/socket.h>
  31. #include <netinet/in.h>
  32.  
  33. #include "ipxd.h"
  34. #include "ipxripd.h"
  35. #include "ipxsapd.h"
  36.  
  37. #define DEVICE_LENGTH (31)
  38. #define MAX_DEVICE    MAX_IFACE
  39. struct ticks_entry {
  40.     char device_name[DEVICE_LENGTH+1];
  41.     int  ticks;
  42. };
  43.  
  44. static struct ipx_interface ifaces[MAX_IFACE];
  45. int time_since_last_bcast=0;
  46. static struct rip_packet rip_in_buf;
  47. static struct sap_packet sap_in_buf;
  48.  
  49. static struct ticks_entry ticks_table[MAX_DEVICE];
  50. int ticks_entries=0;
  51. static char default_ticks_file[] = TICKS_FILE;
  52. static char *ticks_file = default_ticks_file;
  53.  
  54. int passive = 0;
  55.  
  56. volatile int check_request=0;
  57. static volatile int dump_request=0;
  58. static volatile int timer_request=0;
  59. static volatile int terminate=0;
  60. static volatile int scan_ticks_request=0;
  61.  
  62. int new_log_entry=1;
  63. int debug_option=0;
  64. FILE *log_file=stderr;
  65.  
  66. static IPXNet
  67. ifc_net(struct ipx_interface *ifc)
  68. {
  69.     return ntohl(ifc->r_output.dest_addr.sipx_network);
  70. }
  71.  
  72. static void
  73. int_handler()
  74. {
  75.     signal(SIGINT,int_handler);
  76.     dump_request=1;
  77. }
  78.  
  79. static void
  80. timer_handler()
  81. {
  82.     signal(SIGALRM,timer_handler);
  83.     timer_request=1;
  84.     check_request=1;
  85. }
  86.  
  87. static void
  88. terminate_handler()
  89. {
  90.     signal(SIGTERM,terminate_handler);
  91.     terminate=1;
  92. }
  93.  
  94. static void
  95. hup_handler()
  96. {
  97.     signal(SIGHUP,hup_handler);
  98.     scan_ticks_request=1;
  99.     check_request=1;
  100. }
  101.  
  102. struct ipx_interface *
  103. first_interface(void)
  104. {
  105.     int i = first_ifc_index();
  106.  
  107.     if (i < 0)
  108.     {
  109.         return NULL;
  110.     }
  111.  
  112.     return &(ifaces[i]);
  113. }
  114.  
  115. struct ipx_interface *
  116. next_interface(struct ipx_interface *ifc)
  117. {
  118.     int i = next_ifc_index(ifc_get_index(ifc));
  119.  
  120.     if (i < 0)
  121.     {
  122.         return NULL;
  123.     }
  124.  
  125.     return &(ifaces[i]);
  126. }
  127.  
  128. int
  129. ifc_get_index(struct ipx_interface *ifc)
  130. {
  131.     if (ifc == NULL)
  132.     {
  133.         return -1;
  134.     }
  135.     return ifc - ifaces;
  136. }
  137.  
  138. int
  139. first_ifc_index(void)
  140. {
  141.     int i;
  142.  
  143.     for (i = 0; i < MAX_IFACE; i += 1)
  144.     {
  145.         if (ifaces[i].valid != 0)
  146.         {
  147.             return i;
  148.         }
  149.     }
  150.     return -1;
  151. }
  152.  
  153. int
  154. next_ifc_index(int i)
  155. {
  156.     if ((i < 0) || (i >= MAX_IFACE-1))
  157.     {
  158.         return -1;
  159.     }
  160.  
  161.     i = i+1;
  162.  
  163.     while (i < MAX_IFACE)
  164.     {
  165.         if (ifaces[i].valid != 0)
  166.         {
  167.             return i;
  168.         }
  169.         i = i+1;
  170.     }
  171.     return -1;
  172. }
  173.  
  174. static int
  175. first_free_ifc_index(void)
  176. {
  177.     int i;
  178.  
  179.     for (i = 0; i < MAX_IFACE; i += 1)
  180.     {
  181.         if (ifaces[i].valid == 0)
  182.         {
  183.             return i;
  184.         }
  185.     }
  186.     return -1;
  187. }
  188.  
  189. static void
  190. read_ticks_table(void)
  191. {
  192.     char buf[512];
  193.     char device[512];
  194.     int ticks;
  195.     FILE *f = fopen(ticks_file, "r");
  196.  
  197.     ticks_entries = 0;
  198.     if (f == NULL)
  199.     {
  200.         return;
  201.     }
  202.  
  203.     while (fgets(buf, sizeof(buf), f) != NULL)
  204.     {
  205.         if (   (strlen(buf) == 0)
  206.             || (buf[0] == '#'))
  207.         {
  208.             continue;
  209.         }
  210.         if (sscanf(buf, "%s %d", device, &ticks) != 2)
  211.         {
  212.             continue;
  213.         }
  214.         if (strlen(device) > DEVICE_LENGTH)
  215.         {
  216.             fclose(f);
  217.             return;
  218.         }
  219.         strcpy(ticks_table[ticks_entries].device_name, device);
  220.         ticks_table[ticks_entries].ticks = ticks;
  221.         ticks_entries += 1;
  222.  
  223.         if (ticks_entries >= MAX_DEVICE)
  224.         {
  225.             fclose(f);
  226.             return;
  227.         }
  228.     }
  229.     fclose(f);
  230.     return;
  231. }
  232.  
  233. int
  234. find_ticks(char *device)
  235. {
  236.     int i;
  237.     for (i = 0; i < ticks_entries; i += 1)
  238.     {
  239.         if (strcmp(device, ticks_table[i].device_name) == 0)
  240.         {
  241.             return ticks_table[i].ticks;
  242.         }
  243.     }
  244.     return DEFAULT_TICKS;
  245. }
  246.  
  247. static void
  248. dump_ticks(void)
  249. {
  250.     int i;
  251.  
  252.     LOG_ENTRY;
  253.     LOG_START;
  254.     fprintf(log_file, "Ticks table:\n");
  255.     for (i = 0; i < ticks_entries; i += 1)
  256.     {
  257.         fprintf(log_file, "Device: %s, Ticks: %d\n",
  258.             ticks_table[i].device_name,
  259.             ticks_table[i].ticks);
  260.     }
  261.     LOG_END;
  262. }
  263.  
  264. static int
  265. ipx_init_interface(struct ipx_interface *ifc,
  266.            IPXNet network, IPXNode node,
  267.            char *device, int type, void *data)
  268. {
  269.     int result;
  270.  
  271.     ipx_assign_node(ifc->ifnode, node);
  272.  
  273.     ifc->ticks = find_ticks(device);
  274.  
  275.     if ((result = ipx_rip_init_ifc(ifc, network, device, type, data)) != 0)
  276.     {
  277.         return result;
  278.     }
  279.     if ((result = ipx_sap_init_ifc(ifc, network, device, type, data)) != 0)
  280.     {
  281.         return result;
  282.     }
  283.     ifc->valid = 1;
  284.     return 0;
  285. }
  286.  
  287. static int
  288. ipx_create_ifc(IPXNet network, IPXNode node,
  289.            char *device, int type, void *data)
  290. {
  291.     struct ipx_interface *ifc = &(ifaces[first_free_ifc_index()]);
  292.     int result;
  293.  
  294.     if (ifc == NULL)
  295.     {
  296.         LOG_START;
  297.         fprintf(log_file,"too many interfaces (max. %i)\n",
  298.             (int)MAX_IFACE);
  299.         LOG_END;
  300.         return -1;
  301.     }
  302.  
  303.     if (network == 0)
  304.     {
  305.         LOG_START;
  306.         fprintf(log_file,"interface bound to net 0\n");
  307.         LOG_END;
  308.         return -1;
  309.     }
  310.  
  311.     if (   (passive != 0)
  312.         && ((type & IPX_KRT_INTERNAL) != 0))
  313.     {
  314.         LOG_START;
  315.         fprintf(log_file, "passive mode only whithout internal net\n");
  316.         LOG_END;
  317.         return -1;
  318.     }
  319.  
  320.     if ((result = ipx_init_interface(ifc, network, node, device, type,
  321.                      data)) != 0)
  322.     {
  323.         return result;
  324.     }
  325.     
  326.     return 0;
  327. }
  328.  
  329. static void
  330. init(void)
  331. {
  332.     struct itimerval itval;
  333.     int i;
  334.     
  335.     LOG_ENTRY;
  336.     LOG_START;
  337.     fprintf(log_file,"Init start\n");
  338.     LOG_END;
  339.  
  340.     read_ticks_table();
  341.     
  342.     for (i = 0; i < MAX_IFACE; i++)
  343.     {
  344.         ifaces[i].valid = 0;
  345.     }
  346.  
  347.     if (ipx_kern_scan_ifaces(ipx_create_ifc, NULL) != 0)
  348.     {
  349.         exit(1);
  350.     }
  351.  
  352.     itval.it_interval.tv_sec = TIMER_RATE;
  353.     itval.it_value.tv_sec = TIMER_RATE;
  354.     itval.it_interval.tv_usec = 0;
  355.     itval.it_value.tv_usec = 0;
  356.     if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
  357.     {
  358.         LOG_START;
  359.         fprintf(log_file, "FATAL ERROR: can't set itimer: %s\n",
  360.             strerror(errno));
  361.         LOG_END;
  362.         exit(1);
  363.     }
  364.     
  365.     signal(SIGINT,int_handler);
  366.     signal(SIGALRM,timer_handler);
  367.     signal(SIGTERM,terminate_handler);
  368.     signal(SIGHUP,hup_handler);
  369.  
  370.     ipx_rip_initial_broadcasts();
  371.     ipx_sap_initial_broadcasts();
  372.     
  373.     LOG_ENTRY;
  374.     LOG_START;
  375.     fprintf(log_file,"Init end\n");
  376.     LOG_END;
  377. }
  378.  
  379. static int
  380. ipx_visit_ifc(IPXNet network, IPXNode node,
  381.           char *device, int type, void *data)
  382. {
  383.     struct ipx_interface *ifc;
  384.     int result;
  385.  
  386.     if (network == 0)
  387.     {
  388.         return 0;
  389.     }
  390.  
  391.     for (ifc = first_interface();
  392.          ifc != NULL;
  393.          ifc = next_interface(ifc))
  394.     {
  395.         if (ifc_net(ifc) == network)
  396.         {
  397.             ifc->visited = 1;
  398.             return 0;
  399.         }
  400.     }
  401.  
  402.     /* We have a new interface */
  403.  
  404.     ifc = &(ifaces[first_free_ifc_index()]);
  405.  
  406.     if (ifc == NULL)
  407.     {
  408.         LOG_START;
  409.         fprintf(log_file,"too many interfaces (max. %i)\n",
  410.             (int)MAX_IFACE);
  411.         LOG_END;
  412.         return -1;
  413.     }
  414.  
  415.     if ((result = ipx_init_interface(ifc, network, node, device, type,
  416.                      data)) != 0)
  417.     {
  418.         return result;
  419.     }
  420.  
  421.     ipx_rip_initial_broadcast(ifc);
  422.     ipx_sap_initial_broadcast(ifc);
  423.  
  424.     ifc->visited = 1;
  425.     
  426.     return 0;
  427. }
  428.  
  429.  
  430. static void
  431. ipx_check_interfaces(void)
  432. {
  433.     struct ipx_interface *ifc;
  434.  
  435.     for (ifc = first_interface();
  436.          ifc != NULL;
  437.          ifc = next_interface(ifc))
  438.     {
  439.         ifc->visited = 0;
  440.     }
  441.  
  442.     ipx_kern_scan_ifaces(ipx_visit_ifc, NULL);
  443.  
  444.     for (ifc = first_interface();
  445.          ifc != NULL;
  446.          ifc = next_interface(ifc))
  447.     {
  448.         if (ifc->visited == 0)
  449.         {
  450.             /* Interface is down now */
  451.             ipx_sap_down_ifc(ifc);
  452.             ipx_rip_down_ifc(ifc);
  453.             ifc->valid = 0;
  454.         }
  455.     }
  456. }
  457.  
  458.  
  459. static void
  460. run(void)
  461. {
  462.     struct sockaddr_ipx sipx;
  463.     int addr_len=sizeof(sipx);
  464.     int size;
  465.     fd_set rset;
  466.     int result;
  467.     int max_sk;
  468.     struct ipx_interface *ifc = NULL;
  469.     int got_rip, got_sap;
  470.  
  471.     while(1)
  472.     {
  473.         FD_ZERO(&rset);
  474.         max_sk = 0;
  475.         got_rip = got_sap = 0;
  476.  
  477.         for (ifc = first_interface();
  478.              ifc != NULL;
  479.              ifc = next_interface(ifc))
  480.         {
  481.             if (ifc->r_output.sk > max_sk)
  482.             {
  483.                 max_sk = ifc->r_output.sk;
  484.             }
  485.             FD_SET(ifc->r_output.sk, &rset);
  486.  
  487.             if (ifc->s_output.sk > max_sk)
  488.             {
  489.                 max_sk = ifc->s_output.sk;
  490.             }
  491.             FD_SET(ifc->s_output.sk, &rset);
  492.         }        
  493.  
  494.         LOG_ENTRY;
  495.  
  496.         result = select(max_sk+1, &rset, NULL, NULL, NULL);
  497.  
  498.         if (   (result < 0)
  499.             && (errno != EINTR))
  500.         {
  501.             LOG_START;
  502.             fprintf(log_file, "select error: %s\n",
  503.                 strerror(errno));
  504.             LOG_END;
  505.             continue;
  506.         }
  507.  
  508.         size = -1;
  509.  
  510.         if (result == 0)
  511.         {
  512.             LOG_START;
  513.             fprintf(log_file, "select timeout expired\n");
  514.             LOG_END;
  515.             continue;
  516.         }
  517.  
  518.         if (result > 0)
  519.         {
  520.             for (ifc = first_interface();
  521.                  ifc != NULL;
  522.                  ifc = next_interface(ifc))
  523.             {
  524.                 if (FD_ISSET(ifc->r_output.sk, &rset))
  525.                 {
  526.                     size=recvfrom(ifc->r_output.sk,
  527.                               &rip_in_buf,
  528.                               sizeof(rip_in_buf), 0,
  529.                               (struct sockaddr*)&sipx,
  530.                               &addr_len);
  531.                     if (size > 0)
  532.                     {
  533.                         got_rip = 1;
  534.                     }
  535.                     /* only one packet at a time */
  536.                     break;
  537.                 }
  538.                 if (FD_ISSET(ifc->s_output.sk, &rset))
  539.                 {
  540.                     size=recvfrom(ifc->s_output.sk,
  541.                               &sap_in_buf,
  542.                               sizeof(sap_in_buf), 0,
  543.                               (struct sockaddr*)&sipx,
  544.                               &addr_len);
  545.                     if (size > 0)
  546.                     {
  547.                         got_sap = 1;
  548.                     }
  549.                     /* only one packet at a time */
  550.                     break;
  551.                 }
  552.             }
  553.         }
  554.  
  555.         if (size < 0)
  556.         {
  557.             /* One reason can be an interface that died. */
  558.             check_request = 1;
  559.         }
  560.         if (got_rip != 0)
  561.         {
  562.             DL_START;
  563.             fprintf(log_file,"RIP from: ");
  564.             ipx_fprint_saddr(log_file,&sipx);
  565.             fprintf(log_file,"\n");
  566.             ipx_rip_fdump(log_file, &rip_in_buf, size);
  567.             DL_END;
  568.             handle_rip(&rip_in_buf, size, &sipx,ifc);
  569.         }
  570.         if (got_sap != 0)
  571.         {
  572.             DL_START;
  573.             fprintf(log_file,"SAP from: ");
  574.             ipx_fprint_saddr(log_file,&sipx);
  575.             fprintf(log_file,"\n");
  576.             ipx_sap_fdump(log_file, &sap_in_buf, size);
  577.             DL_END;
  578.             handle_sap(&sap_in_buf, size, &sipx,ifc);
  579.         }    
  580.         if (dump_request)
  581.         {
  582.             fdump_routes(log_file);
  583.             fdump_servers(log_file);
  584.             dump_ticks();
  585.             dump_request=0;
  586.         }
  587.         if (timer_request)
  588.         {
  589.             static int rip_broadcast = 0;
  590.             int do_broadcast = 0;
  591.  
  592.             time_since_last_bcast += TIMER_RATE;
  593.             if (time_since_last_bcast >= BROADCAST_TIME/2)
  594.             {
  595.                 do_broadcast = 1;
  596.                 rip_broadcast = (rip_broadcast==0) ? 1 : 0;
  597.                 time_since_last_bcast -= BROADCAST_TIME/2;
  598.             }
  599.  
  600.             LOG_ENTRY;
  601.             ipx_rip_do_aging(TIMER_RATE,
  602.                         (do_broadcast  != 0)
  603.                      && (rip_broadcast != 0));
  604.             LOG_ENTRY;
  605.             ipx_sap_do_aging(TIMER_RATE,
  606.                         (do_broadcast!=0)
  607.                      && (rip_broadcast == 0));
  608.  
  609.             timer_request=0;
  610.         }
  611.         if (check_request)
  612.         {
  613.             ipx_check_interfaces();
  614.             check_request = 0;
  615.         }
  616.         if (scan_ticks_request)
  617.         {
  618.             read_ticks_table();
  619.             scan_ticks_request = 0;
  620.         }
  621.         if (terminate)
  622.         {
  623.             LOG_START;
  624.             if (terminate==1)
  625.                 fprintf(log_file,
  626.                     "exiting on signal 15 (SIGTERM)\n");
  627.             else
  628.                 fprintf(log_file,
  629.                     "exiting on signal 1 (SIGHUP)\n");
  630.             LOG_END;
  631.             return;
  632.         }
  633.     }
  634. }
  635.  
  636. static void
  637. help()
  638. {
  639.     fprintf(stderr,
  640.         "IPX routing daemon v0.91, (c) Ales Dryak, 1995\n"
  641.         "Usage: ipxd [options]\n");
  642. }
  643.  
  644. static int
  645. parse_cmdline(int argc,char** argv)
  646. {
  647.     char* log_name = DEFAULT_LOGNAME;
  648.     int opt;
  649.  
  650.     while ((opt = getopt(argc, argv, "dt:l:p")) != EOF)
  651.     {
  652.         switch (opt)
  653.         {
  654.         case 'd':
  655.             debug_option=1;
  656.             break;
  657.         case 't':
  658.             ticks_file = optarg;
  659.             break;
  660.         case 'l':
  661.             log_name = optarg;
  662.             break;
  663.         case 'p':
  664.             passive = 1;
  665.             break;
  666.         default:
  667.             fprintf(stderr,
  668.                 "Unknown command line option %s\n",*argv);
  669.             help();
  670.             exit(1);
  671.         }
  672.     }
  673.     if (optind != argc)
  674.     {
  675.         fprintf(stderr,"Too many parameters");
  676.         help();
  677.         exit(1);
  678.     }
  679.     if (debug_option)
  680.     {
  681.         log_file=stdout;
  682.         return 0;
  683.     }
  684.     if ((log_file=fopen(log_name,"a"))==NULL)
  685.     {
  686.         perror(log_name);
  687.         exit(1);
  688.     }
  689.     return 1;
  690. }
  691.  
  692. static void
  693. daemonize()
  694. {
  695.     int fd,c;
  696.     
  697.     if ((c = fork()) > 0) exit(0);
  698.       if (c < 0)
  699.       {
  700.         fprintf(stderr, "ipxripd: can't fork: %s\n",strerror(errno));
  701.         exit(1);
  702.     }
  703.  
  704.     close(0);
  705.     close(1);
  706.     close(2);
  707.     if ((fd = open("/dev/tty", O_RDWR)) >= 0) 
  708.     {
  709.         ioctl(fd, TIOCNOTTY, NULL);
  710.         close(fd);
  711.     }
  712. }
  713.  
  714. int
  715. main(int argc,char** argv)
  716. {
  717.     if (parse_cmdline(argc,argv))
  718.     {
  719.         daemonize();
  720.     }
  721.     init();
  722.     run();
  723.     ipx_rip_done();
  724.     ipx_sap_done();
  725.     return 0;
  726. }
  727.  
  728.